﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Diagnostics;

namespace ALProtocol.Tcp
{
    /// <summary>
    /// 表示tcp客户端。
    /// </summary>
    public class TcpClient  
    {
        private Socket m_socket;
        /// <summary>
        /// 关联的会话。
        /// </summary>
        private TcpSession m_session;

        /// <summary>
        /// 本地地址。
        /// </summary>
        public IPEndPoint LocalEndPoint { get { return (IPEndPoint)m_socket.LocalEndPoint; } }

        Action<TcpSession, bool> m_sessionChanged;
        /// <summary>
        /// 会话改变通知。
        /// </summary>
        public event Action<TcpSession, bool> SessionChanged
        {
            add { m_sessionChanged += value; }
            remove { m_sessionChanged -= value; }
        }
        /// <summary>
        /// 
        /// </summary>
        public TcpClient()
        {
            Reset();
        }

        /// <summary>
        /// 客户端重置。
        /// </summary>
        public void Reset()
        {
            Close();
            m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }
        /// <summary>
        /// 关闭。
        /// </summary>
        public void Close()
        {
            if (m_socket != null)
            {
                m_socket.Dispose();
            }
        }

        /// <summary>
        /// 连接远端。
        /// </summary>
        /// <param name="remote"></param>
        /// <returns></returns>
        public bool Connect(IPEndPoint remote)
        {
            try
            {
                m_socket.Connect(remote);
                m_session = new TcpSession(m_socket);
                m_session.Disposed += new Action<TcpSession>(SessionDisposed);
                if (m_sessionChanged != null)
                {
                    m_sessionChanged(m_session, true);
                }
                return true;
            }
            catch
            {
                return false;
            }
        }
        /// <summary>
        /// 会话关闭通知。
        /// </summary>
        /// <param name="session"></param>
        void SessionDisposed(TcpSession session)
        {
            Debug.Assert(m_session == session);
            if (m_sessionChanged != null)
            {
                m_sessionChanged(session, false);
            }
            m_session = null; 
        }
        /// <summary>
        /// 绑定本地地址。
        /// </summary>
        /// <returns></returns>
        public bool Bind(IPEndPoint local)
        {
            try
            {
                m_socket.Bind(local);
            }
            catch
            {
                return false;
            }
            return true;
        }
    }
}
